﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace RecipeRecommender
{
    public partial class Form4 : Form
    {
        private Recipe cRecipeToAdapt;

        private RecipeQuery cRecipeQuery;

        private Recipe cCurrentAdaptedRecipe;
        public Form4(Recipe cCurrent, RecipeQuery cQuery)
        {
            cRecipeToAdapt = cCurrent;
            cRecipeQuery = cQuery;
            

            InitializeComponent();
            displayOriginalRecipe(cCurrent);
            substituteIngredientLabel.Text = "";
            if (cCurrent.Vegetarian== false && cQuery.Vegetarian==true)
            {
                nonVegToVegButton.Enabled = true;
            }
            else
            {
                nonVegToVegButton.Enabled = false;
            }
            storeRecipeButton.Enabled = false;
        }
        public void AdaptIngredients()
        {
            Recipe cNewRecipe = cRecipeToAdapt.clone();


            //find ingredient in new recipe that is not in recipe query, preferably a meat

            //Ingredient cIngToSub = FindMeatIngredientNotInQuery();

            Ingredient cIngToSub = findIngredientTypeNotInQuery("Meat");

            //if found, find a meat ingredient in the recipe query

            Ingredient cIngQuery = null;
            if (cIngToSub != null)
            {
                //cIngQuery = findMeatIngredientInRecipeQuery();
                cIngQuery = findIngredientTypeInRecipeQuery("Meat");
            }
            //if not successful, find a vegetable ingredient in new recipe that is not in recipe query
            if (cIngToSub == null || cIngQuery == null)
            {
                //cIngToSub = FindVegIngredientNotInQuery();

                cIngToSub = findIngredientTypeNotInQuery("Vegetable");
                //if found, find a vegetable ingredient in the recipe query
                if (cIngToSub != null)
                {
                    //cIngQuery = findVegIngredientInRecipeQuery();
                    cIngQuery = findIngredientTypeInRecipeQuery("Vegetable");
                }
            }

            //if not successful, find a carbohydrate ingredient in new recipe that is not in recipe query
            if (cIngToSub == null || cIngQuery == null)
            {
                //cIngToSub = FindVegIngredientNotInQuery();

                cIngToSub = findIngredientTypeNotInQuery("Carbohydrate");
                //if found, find a vegetable ingredient in the recipe query
                if (cIngToSub != null)
                {
                    //cIngQuery = findVegIngredientInRecipeQuery();
                    cIngQuery = findIngredientTypeInRecipeQuery("Carbohydrate");
                }
            }
            

            //if not successful, find cooking oil ingredient to replace
            if (cIngToSub == null || cIngQuery == null)
            {
                

                cIngToSub = findIngredientTypeNotInQuery("Cooking oil");
                //if found, find a cooking oil ingredient in the recipe query
                if (cIngToSub != null)
                {
                    
                    cIngQuery = findIngredientTypeInRecipeQuery("Cooking oil");
                }
            }

            //if not successful, find leaf ingredient to replace
            if (cIngToSub == null || cIngQuery == null)
            {
               

                cIngToSub = findIngredientTypeNotInQuery("Leaf");
                //if found, find a leaf ingredient in the recipe query
                if (cIngToSub != null)
                {
                    
                    cIngQuery = findIngredientTypeInRecipeQuery("Leaf");
                }
            }


            //if not successful find sauce ingredient to replace
            if (cIngToSub == null || cIngQuery == null)
            {


                cIngToSub = findIngredientTypeNotInQuery("Sauce");
                //if found, find a leaf ingredient in the recipe query
                if (cIngToSub != null)
                {

                    cIngQuery = findIngredientTypeInRecipeQuery("Sauce");
                }
            }



           

            if (cIngToSub != null && cIngQuery != null)
            {
                //perform replacement of ingredient pairs
                performIngredientReplacement(cNewRecipe, cIngToSub, cIngQuery);
                performCookingInstructionReplacement(cNewRecipe, cIngToSub, cIngQuery);
                performNameReplacement(cNewRecipe, cIngToSub, cIngQuery);


                cNewRecipe.Similarity = RecipeUtil.getSimilarityScore(cRecipeQuery, cNewRecipe);
                substituteIngredientLabel.Text = "Substituted " + cIngToSub.Name + " with "+ cIngQuery.Name;
                displayAdaptedRecipe(cNewRecipe);
                cCurrentAdaptedRecipe = cNewRecipe;
                storeRecipeButton.Enabled = true;
            }
            else
            {
                //display error
                MessageBox.Show("Unable to find an ingredient to substitute! Ingredient to substitute is taken from recipe query.");
            }





           
        }

        private void performIngredientReplacement(Recipe cRecipe, Ingredient cIngToSub, Ingredient cNewIng)
        {

            //check through all the ingredients
            
            //foreach (Ingredient cIng in cRecipe.Ingredients)
            //{
            //    //check if the name is the same
            //    if (cIng.Name == cIngToSub.Name)
            //    {
            //        cRecipe.Ingredients.Remove(cIng);//remove the ingredients
            //        break;
            //    }
            //}

            for (int i = 0; i < cRecipe.Ingredients.Count(); i++)
            {
                if (cRecipe.Ingredients[i].Name == cIngToSub.Name)
                {
                    cRecipe.Ingredients.Remove(cRecipe.Ingredients[i]);//remove the ingredients
                    i = 0;//set it back to the first
                }
            }

            cRecipe.Ingredients.Add(cNewIng);
            

        }

        private void performNameReplacement(Recipe cRecipe, Ingredient cIngToSub, Ingredient cNewIng)
        {
            string strNew = Regex.Replace(cRecipe.Name, cIngToSub.Name, cNewIng.Name, RegexOptions.IgnoreCase);
            cRecipe.Name = strNew;
        }

        private void displayAdaptedRecipe (Recipe cRecipe)
        {
            adaptedCuisineTextBox.Text = cRecipe.Cuisine.Name;
            adaptedMealTypeTextBox.Text = cRecipe.MealType.Name;
            adaptedCookingMethodTextBox.Text = cRecipe.CookingMethod.Name;
            adaptedCookingInstructionRichTextBox.Text = cRecipe.CookingInstructions;
            adaptedNameTextBox.Text = cRecipe.Name;
            adaptedSimilarityTextBox.Text = cRecipe.Similarity.ToString();
            adaptedHalalCheckBox.Checked = (bool)cRecipe.Halal;
            adaptedHealthyCheckBox.Checked = (bool)cRecipe.Healthy;
            adaptedVegetarianCheckBox.Checked = (bool)cRecipe.Vegetarian;
            adaptedSpicyCheckBox.Checked = (bool)cRecipe.Spicy;
            adaptedCookingTimeTextBox.Text = cRecipe.CookingTime.ToString();
            adaptedServingPortionTextBox.Text = cRecipe.ServingPortion.ToString();
            adaptedIngredientsListBox.Items.Clear();
            adaptedSimilarityTextBox.Text = cRecipe.Similarity.ToString();
            foreach (Ingredient ingredient in cRecipe.Ingredients)
            {
                adaptedIngredientsListBox.Items.Add(ingredient.Name);
            }
        }


        private void displayOriginalRecipe(Recipe cRecipe)
        {
            rCuisineTextBox.Text = cRecipe.Cuisine.Name;
            rMealTypetextBox.Text = cRecipe.MealType.Name;
            rCookingMethodTextBox.Text = cRecipe.CookingMethod.Name;
            rCookingInstructionRichTextBox.Text = cRecipe.CookingInstructions;
            rNameTextBox.Text = cRecipe.Name;
            similarityTextBox.Text = cRecipe.Similarity.ToString();
            rHalalCheckBox.Checked = (bool)cRecipe.Halal;
            rHealthyCheckBox.Checked = (bool)cRecipe.Healthy;
            rVegetarianCheckBox.Checked = (bool)cRecipe.Vegetarian;
            rSpicyCheckBox.Checked = (bool)cRecipe.Spicy;
            rCookingTimeTextBox.Text = cRecipe.CookingTime.ToString();
            rServingPortionTextBox.Text = cRecipe.ServingPortion.ToString();
            rIngredientListBox.Items.Clear();
            similarityTextBox.Text = cRecipe.Similarity.ToString();
            foreach (Ingredient ingredient in cRecipe.Ingredients)
            {
                rIngredientListBox.Items.Add(ingredient.Name);
            }
        }

        private void performCookingInstructionReplacement (Recipe cRecipe, Ingredient cIngToSub, Ingredient cNewIng)
        {
            string strWord;
            
            bool bFound = cRecipe.CookingInstructions.Contains(cIngToSub.Name);

            if (bFound)
            {
                strWord = cIngToSub.Name;
            }


            //if first letter starts with upper case
            //string strNew = cRecipe.CookingInstructions.Replace (cIngToSub.Name, cNewIng.Name);

            
            //if first letter starts with lower case
            //strNew = cRecipe.CookingInstructions.Replace(cIngToSub.Name.ToLower(), cNewIng.Name.ToLower());


            string strNew = Regex.Replace(cRecipe.CookingInstructions, cIngToSub.Name, cNewIng.Name, RegexOptions.IgnoreCase);
            cRecipe.CookingInstructions = strNew;
        }

        private Ingredient findIngredientTypeNotInQuery(string strIngredientType)
        {
            List<Ingredient> cIngredientList = IngredientUtil.IngredientList;



            Ingredient ingredientType = IngredientUtil.getIngredientByName(strIngredientType);
            int[] nTypeValue = ingredientType.Value;

            Ingredient cIngToSub = null;

            int nLevel = IngredientUtil.getLevel(ingredientType);


            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipeToAdapt.Ingredients)
            {
                int[] nIngValue = cIng.Value;


                //check level

                if (nLevel == 2)
                {
                    if (nIngValue[0] == nTypeValue[0] && nIngValue[1] == nTypeValue[1])
                    {
                        bool bFound = false;

                        //check if it is in the query list
                        foreach (Ingredient cIngQuery in cRecipeQuery.Ingredients)
                        {
                            if (cIngQuery.Name == cIng.Name)
                            {
                                bFound = true;
                            }

                        }


                        //store as substitute ingredient if it is not found in the query list
                        if (!bFound)
                        {
                            cIngToSub = cIng.clone();
                        }
                    }
                }
                else if (nLevel == 3)
                {
                    if (nIngValue[0] == nTypeValue[0] && nIngValue[1] == nTypeValue[1] && nIngValue[2] == nTypeValue[2])
                    {
                        bool bFound = false;

                        //check if it is in the query list
                        foreach (Ingredient cIngQuery in cRecipeQuery.Ingredients)
                        {
                            if (cIngQuery.Name == cIng.Name)
                            {
                                bFound = true;
                            }

                        }


                        //store as substitute ingredient if it is not found in the query list
                        if (!bFound)
                        {
                            cIngToSub = cIng.clone();
                        }
                    }
                }
            }


            return cIngToSub;
        }

        private Ingredient FindMeatIngredientNotInQuery()
        {
            List<Ingredient> cIngredientList = IngredientUtil.IngredientList;

           
            //find meat number
            /*
            int[] nMeatValue= new int[4];
            foreach (Ingredient cIng in cIngredientList)
            {
                if (cIng.Name.ToLower() == "meat")
                {
                    nMeatValue = cIng.Value;
                }
            }
            */
            Ingredient meatIngredient = IngredientUtil.getIngredientByName("Meat");
            int[] nMeatValue  = meatIngredient.Value;

            Ingredient cIngToSub=null;

            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipeToAdapt.Ingredients)
            {
                int[] nIngValue = cIng.Value;

                if (nIngValue[0] == nMeatValue[0] && nIngValue[1] == nMeatValue[1])
                {
                    bool bFound = false;

                    //check if it is in the query list
                    foreach (Ingredient cIngQuery in cRecipeQuery.Ingredients)
                    {
                        if (cIngQuery.Name == cIng.Name)
                        {
                            bFound = true;
                        }
                        
                    }


                    //store as substitute ingredient if it is not found in the query list
                    if (!bFound)
                    {
                        cIngToSub = cIng.clone();
                    }
                }
            }


            return cIngToSub;

        }

        private Ingredient FindVegIngredientNotInQuery()
        {
            List<Ingredient> cIngredientList = IngredientUtil.IngredientList;


            //find meat number
            /*
            int[] nMeatValue= new int[4];
            foreach (Ingredient cIng in cIngredientList)
            {
                if (cIng.Name.ToLower() == "meat")
                {
                    nMeatValue = cIng.Value;
                }
            }
            */
            Ingredient vegIngredient = IngredientUtil.getIngredientByName("Vegetable");
            int[] nVegValue = vegIngredient.Value;

            Ingredient cIngToSub = null;

            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipeToAdapt.Ingredients)
            {
                int[] nIngValue = cIng.Value;

                if (nIngValue[0] == nVegValue[0] && nIngValue[1] == nVegValue[1])
                {
                    bool bFound = false;

                    //check if it is in the query list
                    foreach (Ingredient cIngQuery in cRecipeQuery.Ingredients)
                    {
                        if (cIngQuery.Name == cIng.Name)
                        {
                            bFound = true;
                        }

                    }


                    //store as substitute ingredient if it is not found in the query list
                    if (!bFound)
                    {
                        cIngToSub = cIng.clone();
                    }
                }
            }


            return cIngToSub;

        }


        private Ingredient findIngredientTypeInRecipeQuery(string strIngredientType)
        {
            Ingredient ingredientType = IngredientUtil.getIngredientByName(strIngredientType);
            int[] nTypeValue = ingredientType.Value;

            Ingredient cIngToSub = null;

            int nLevel = IngredientUtil.getLevel(ingredientType) ;

            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipeQuery.Ingredients)
            {
                int[] nIngValue = cIng.Value;

               
                if (nLevel == 3)
                {
                    if (nIngValue[0] == nTypeValue[0] && nIngValue[1] == nTypeValue[1] && nIngValue[2] == nTypeValue[2])
                    {
                        cIngToSub = cIng.clone();
                    }
                }
                else if (nLevel == 2)
                {
                    if (nIngValue[0] == nTypeValue[0] && nIngValue[1] == nTypeValue[1])
                    {
                        cIngToSub = cIng.clone();
                    }
                }
            }


            return cIngToSub;
        }

        private Ingredient findMeatIngredientInRecipeQuery()
        {
           
            //find meat number
            /*
            int[] nMeatValue = new int[4];
            foreach (Ingredient cIng in IngredientUtil.IngredientList)
            {
                if (cIng.Name.ToLower() == "meat")
                {
                    nMeatValue = cIng.Value;
                }
            }
            */

            Ingredient meatIngredient =  IngredientUtil.getIngredientByName("Meat");
           int[] nMeatValue = meatIngredient.Value;

            Ingredient cIngToSub = null;

            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipeQuery.Ingredients)
            {
                int[] nIngValue = cIng.Value;

                if (nIngValue[0] == nMeatValue[0] && nIngValue[1] == nMeatValue[1])
                {

                   cIngToSub = cIng.clone();
               
                }
            }


            return cIngToSub;
        }



        private Ingredient findVegIngredientInRecipeQuery()
        {
            Ingredient vegIngredient = IngredientUtil.getIngredientByName("Vegetable");
            int[] nVegValue = vegIngredient.Value;

            Ingredient cIngToSub = null;

            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipeQuery.Ingredients)
            {
                int[] nIngValue = cIng.Value;

                if (nIngValue[0] == nVegValue[0] && nIngValue[1] == nVegValue[1])
                {

                    cIngToSub = cIng.clone();

                }
            }


            return cIngToSub;
        }

        private List<Ingredient> FindListOfIngredientsInRecipe(Recipe cRecipe, string strIngredientType)
        {
            Ingredient ingredientType = IngredientUtil.getIngredientByName(strIngredientType);
            int[] nTypeValue = ingredientType.Value;

            Ingredient cIngToSub = null;

            int nLevel = IngredientUtil.getLevel(ingredientType);
            List<Ingredient> cList = new List<Ingredient>();

            //find the meat in new recipe
            foreach (Ingredient cIng in cRecipe.Ingredients)
            {
                int[] nIngValue = cIng.Value;


                if (nLevel == 3)
                {
                    if (nIngValue[0] == nTypeValue[0] && nIngValue[1] == nTypeValue[1] && nIngValue[2] == nTypeValue[2])
                    {
                        cIngToSub = cIng.clone();
                        cList.Add(cIngToSub);

                    }
                }
                else if (nLevel == 2)
                {
                    if (nIngValue[0] == nTypeValue[0] && nIngValue[1] == nTypeValue[1])
                    {
                        cIngToSub = cIng.clone();
                        cList.Add(cIngToSub);
                    }
                }
            }


            return cList;
        }



        private void AdaptNonVegToVeg()
        {
            substituteIngredientLabel.Text = "";
            Recipe cNewRecipe = new Recipe();

            cNewRecipe = cRecipeToAdapt.clone();

            List<Ingredient> cIngList = FindListOfIngredientsInRecipe(cNewRecipe, "Meat");

            if (cIngList.Count() > 0)
            {
                bool bRecipeChanged = false;
                bool bIngredientNotSubstituted = false;
                for (int i = 0; i < cIngList.Count(); i++)
                {
                    ///get map of ingredient
                    ///
                    List<Ingredient> cReplaceIngredients = new List<Ingredient>();
                    cReplaceIngredients = IngredientUtil.getVegetarianIngredient(cIngList[i]);


                    Ingredient cIngredientSub = null;


                    //check if any ingredient is in recipe query and select that one
                    if (cReplaceIngredients!= null)
                    {
                        foreach (Ingredient cReplaceIng in cReplaceIngredients)
                        {
                            if (checkInRecipeQuery(cReplaceIng))
                            {
                                cIngredientSub = cReplaceIng;
                                break;
                            }
                        }
                    }
                    if (cIngredientSub == null && cReplaceIngredients != null)
                    {
                        //choose any ingredient
                        int nNum;
                        Random rand = new Random();

                        nNum = rand.Next(0, cReplaceIngredients.Count()-1);
                        cIngredientSub = cReplaceIngredients[nNum].clone();

                        
                    }

                   
                    if (cIngredientSub != null)
                    {
                         //replace ingredient
                        performIngredientReplacement(cNewRecipe, cIngList[i], cIngredientSub);
                        //replace cooking instruction
                        performCookingInstructionReplacement(cNewRecipe,cIngList[i], cIngredientSub);
                         //replace name
                        performNameReplacement(cNewRecipe, cIngList[i], cIngredientSub);
                        substituteIngredientLabel.Text += "Replaced " + cIngList[i].Name + " with " + cIngredientSub.Name + ".\n ";
                        bRecipeChanged = true;
                    }
                    else
                    {
                        bIngredientNotSubstituted = true;
                        MessageBox.Show ("Could not find substitute vegetarian ingredient for " + cIngList[i] + ".");
                    }

                    


                    


                }
                if (bRecipeChanged && !bIngredientNotSubstituted)
                {
                    cNewRecipe.Vegetarian = true;
                    cNewRecipe.Similarity = RecipeUtil.getSimilarityScore(cRecipeQuery, cNewRecipe);
                    displayAdaptedRecipe(cNewRecipe);
                    cCurrentAdaptedRecipe = cNewRecipe;
                    storeRecipeButton.Enabled = true;
                }
            }
            else
            {
                MessageBox.Show("No meat ingredients to convert");
            }
        }

        private bool checkInRecipeQuery(Ingredient cIngCheck)
        {
            foreach (Ingredient cIng in cRecipeQuery.Ingredients)
            {
                if (cIng.Name == cIngCheck.Name)
                {
                    return true;
                }
            }
            return false;
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            AdaptIngredients();
        }

        private void nonVegToVegButton_Click(object sender, EventArgs e)
        {
            AdaptNonVegToVeg();
        }

        private void storeRecipeButton_Click(object sender, EventArgs e)
        {
            if (cCurrentAdaptedRecipe != null)
            {
                cCurrentAdaptedRecipe.Name = adaptedNameTextBox.Text;
                if (RecipeUtil.writeRecipe(cCurrentAdaptedRecipe))
                {
                    MessageBox.Show("Recipe Stored");
                    this.Close();
                }
                
            }
        }

        private void adaptedNameTextBox_TextChanged(object sender, EventArgs e)
        {
           
            
        }
    }

    

}
